package br.ufrj.dcc.so.trab2;

import java.util.ArrayList;
import java.util.List;

//import com.sun.java.util.jar.pack.Instruction.Switch;

import br.ufrj.dcc.so.trab2.entity.Cliente;
import br.ufrj.dcc.so.trab2.entity.Oficial;
import br.ufrj.dcc.so.trab2.entity.Praca;
import br.ufrj.dcc.so.trab2.entity.Sargento;

public class BarbeariaRecrutaZero implements Barbearia {

	private List<Cliente> oficiaisList;
	private List<Cliente> sargentosList;
	private List<Cliente> pracasList;

	private Object travaOficiaisList;
	private Object travaSargentosList;
	private Object travaPracasList;
	
	private Forte forte;

	public BarbeariaRecrutaZero(Forte forte) {
		this.forte = forte;
		oficiaisList = new ArrayList<Cliente>();
		sargentosList = new ArrayList<Cliente>();
		pracasList = new ArrayList<Cliente>();

		travaOficiaisList = new Object();
		travaSargentosList = new Object();
		travaPracasList = new Object();
	}

	@Override
	public int getNumClientesEspera() {
		// TODO - contagem inconsistente
		return getNumOficiaisEspera() + getNumPracasEspera()
				+ getNumSargentosEspera();
	}

	/**
	 * @see Barbearia#addClienteEspera(Cliente)
	 */
	@Override
	public void addClienteEspera(Cliente cliente) {
		//TODO - refatorar colocando pergunta do tipo de cliente dentro dele mesmo! 
		if (cliente instanceof Oficial) {
			addOficial(cliente);
		}

		if (cliente instanceof Sargento) {
			addSargento(cliente);
		}

		if (cliente instanceof Praca) {
			addPraca(cliente);
		}
	}

	private void addPraca(Cliente cliente) {
		Praca praca = (Praca) cliente;
		synchronized (travaPracasList) {
			pracasList.add(praca);
		}
	}

	private void addOficial(Cliente cliente) {
		Oficial oficial = (Oficial) cliente;
		synchronized (travaOficiaisList) {
			oficiaisList.add(oficial);
		}
	}

	private void addSargento(Cliente cliente) {
		Sargento sargento = (Sargento) cliente;
		synchronized (travaSargentosList) {
			sargentosList.add(sargento);
		}
	}

	@Override
	public int getNumOficiaisEspera() {
		return oficiaisList.size();
	}

	@Override
	public int getNumSargentosEspera() {
		return sargentosList.size();
	}

	@Override
	public int getNumPracasEspera() {
		return pracasList.size();
	}

	@Override
	public void close() {
		// TODO - Indicar, de alguma forma, que a barbearia deve parar quando
		// acabar os clientes nas fila! Ou seja, a thread deve morrer.
	}

	@Override
	/*
	 * Método que retira o primeiro da fila do tipo selecionado
	 * 
	 * @param tipo Tipo de Cliente que se quer atender.
	 */
	public Cliente primeiroDaFila(int tipo) {
		Cliente cliente = null;

		// TODO - Sincronismo/Exclus�o mutua nas filas

		/*
		 * - Garantir sincronismos nas filas entre os Barbeiros e o Sargento
		 * Tainha - Garantir exclus�o mutua entre os Barbeiros e o Sargento
		 * Tainha
		 * 
		 * - O Tenente escovinah vai precisar de acesso a lista, mas como ele s�
		 * vai ler acredito que n�o ter� problema
		 */

		
		
		switch (tipo) {
		// Oficial
		case 0:
			synchronized (travaOficiaisList) {
				if (oficiaisList.size() > 0)
					oficiaisList.remove(0);// primeiro ?
				break;
			}

			// sargentos
		case 1:
			synchronized (travaSargentosList) {
				if (sargentosList.size() > 0)
					sargentosList.remove(0);// primeiro ?
				break;
			}

			// pracas
		case 2:
			synchronized (travaPracasList) {
				if (pracasList.size() > 0)
					pracasList.remove(0);// primeiro ?
				break;
			}
		}
		

		return cliente;

	}
}
